package samse.exam.test1;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class PageChanger extends View {
	private static final String TAG="PageChanger";
					
	private final static int INTERVAL = 20;
	private final static int ACCEL = 2;
	private Timer mTimer;;	
	private boolean mAnimating=false;

	private final static int PAGE_BASE = 0;
	private final static int PAGE_CHANGE = 1;
	private final static int PAGE_LEFTGRIP = 2;
	private final static int PAGE_RIGHTGRIP = 3;
	
	public final static int DIRECTION_PREV=0;
	public final static int DIRECTION_NEXT=1;
	
	private int	mDirection = DIRECTION_NEXT;
	private int mInterval = INTERVAL;
	
	private Bitmap[] mBitmap = new Bitmap[4];	
	private Bitmap merged_bitmap = null;
	
	private Matrix	mMatrix = new Matrix();
	private Paint mPaint = new Paint();
	
	private Handler mHandler = new Handler();

	public PageChanger(Context context) {
		this(context, null);
		init(INTERVAL);
	}
	
	public PageChanger(Context context,
			AttributeSet attrs) {
		this(context, attrs, android.R.attr.animation);
		init(INTERVAL);
	}
	public PageChanger(Context context,
             AttributeSet attrs,
             int defStyle) {	
		super(context, attrs, defStyle);
		
		init(INTERVAL);
	}
	
	public void init(int interval) {
		mInterval = interval;
	}
	
	public void setBitmap(Bitmap base, Bitmap change) {
		mBitmap[PAGE_BASE] = base;
		mBitmap[PAGE_CHANGE] = change;		
	}		
	
	public void setGrip(Bitmap leftGrip, Bitmap rightGrip) {
		mBitmap[PAGE_LEFTGRIP] = leftGrip;
		mBitmap[PAGE_RIGHTGRIP] = rightGrip;
	}
	
	/**
	 * 
	 * 
	 * @param direction 
	 */
	public void onShotPage(int direction) {
		startAnimation(direction);
		invalidate();
	}
	
	/**
	 * 
	 * @param x
	 * @param y
	 */
	public void onMoving(float x, float y) {
		mPosition = (int)x;
		invalidate();
	}

	//private class GestureHandler {
	//	boolean mRunning=false;
	//	public GestureHandler() {			
	//	}
	//	public void onTouchEvent(MotionEvent event) {
	//		event.getAction();
	//	}		
	//}
	
	//GestureHandler gh = new GestureHandler();
	static float prevX = 0;
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		
		Log.d(TAG, "onTouchEvent --> " + event);
		//gh.onTouchEvent(event);
		int action = event.getAction();
		if(action ==0) {
			initAnimation(mDirection);
			prevX = event.getX();
		}if(action ==2 ) {			
			onMoving(event.getX(), event.getY());
			if( (prevX - event.getX()) >= 0 )	mDirection = DIRECTION_NEXT;
			else	mDirection = DIRECTION_PREV;
			
		}else if(action ==1) {
			//stopAnimation();			
			//if( (prevX - event.getX()) >= 0 ) mDirection = DIRECTION_NEXT;
			//else	mDirection = DIRECTION_PREV;			
			flushAnimation(mDirection);
		}
		
		return super.onTouchEvent(event);
	}

	@Override
	protected void onFinishInflate() {
		// TODO Auto-generated method stub
		super.onFinishInflate();
	}
	
	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onLayout: changed=" + changed + ", left=" + left + ", top=" + top + ", right=" + right);		
		super.onLayout(changed, left, top, right, bottom);
	}
	
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onMeasure: widthMeasureSpec=" + widthMeasureSpec + ", heightMeasureSpec=" + heightMeasureSpec);		
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onSizeChanged: w=" + w + ", h=" + h + ", oldw=" + oldw + ", oldh=" + oldh);
		super.onSizeChanged(w, h, oldw, oldh);
	}
	
	@Override
	protected void onFocusChanged(boolean gainFocus, int direction,
			Rect previouslyFocusedRect) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onFocusChanged : gainFocus=" + gainFocus + ", direction=" + direction + ", previousFocusedRect=" + previouslyFocusedRect);
		super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
	}
	
	@Override
	protected void onWindowVisibilityChanged(int visibility) {
		// TODO Auto-generated method stub
		Log.d(TAG, "onWindowVisibilityChagned =" + visibility);
		if(mAnimating && (visibility==INVISIBLE || visibility==GONE)) {
			stopAnimation();
		}
		super.onWindowVisibilityChanged(visibility);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		if(isAnimating()) {
			Rect src, dst;
			if(mDirection==DIRECTION_PREV) {
				// Position : 0 -> width
				src = new Rect(mPosition, 0, mWidth, mHeight);
				dst = new Rect(mPosition, 0, mWidth, mHeight);
				canvas.drawBitmap(mBitmap[PAGE_BASE], src, dst, mPaint);
				
				src.set(mWidth-mPosition, 0, mWidth, mHeight);
				dst.set(0, 0, mPosition, mHeight);
				canvas.drawBitmap(mBitmap[PAGE_CHANGE], src, dst, mPaint );
				
				if(mBitmap[PAGE_LEFTGRIP]!=null) {
					int gripWidth = mBitmap[PAGE_LEFTGRIP].getWidth();
					int gripHeight = mBitmap[PAGE_LEFTGRIP].getHeight();
										
					int srcX = gripWidth - mPosition;
					if(srcX<0) srcX = 0;					
					src = new Rect( srcX, 0, gripWidth, gripHeight);
					
					int dstX = 0;
					if(mPosition>gripWidth) dstX = mPosition-gripWidth;					
					int dstW = mPosition;
					if(mPosition>gripWidth) dstW = dstX+gripWidth;
					dst = new Rect(dstX, 0, dstW, mHeight);					
					canvas.drawBitmap(mBitmap[PAGE_LEFTGRIP], src, dst, mPaint);
				}
				
			}else {				
				// Position : Width -> width
				src = new Rect(0, 0, mPosition, mHeight);
				dst = new Rect(0, 0, mPosition, mHeight); //mWidth-mPosition, 0, mWidth, mHeight);
				canvas.drawBitmap(mBitmap[PAGE_BASE], src, dst, mPaint);
				
				src.set(0, 0, mWidth-mPosition, mHeight);
				dst.set(mPosition, 0, mWidth, mHeight);				
				canvas.drawBitmap(mBitmap[PAGE_CHANGE], src, dst, mPaint );
				
				if(mBitmap[PAGE_RIGHTGRIP]!=null) {
					int gripWidth = mBitmap[PAGE_RIGHTGRIP].getWidth();
					int gripHeight = mBitmap[PAGE_RIGHTGRIP].getHeight();
					int srcW = mWidth-mPosition;
					if(srcW>gripWidth) srcW = gripWidth;
					src.set(0, 0, srcW, gripHeight);
					
					int dstW = mWidth;
					if(mPosition<mWidth-gripWidth) dstW = mPosition+gripWidth;
					dst.set(mPosition, 0, dstW, mHeight); 
					canvas.drawBitmap(mBitmap[PAGE_RIGHTGRIP], src, dst, mPaint);
				}
			}				
		}else {
			if(mBitmap[PAGE_BASE]!=null)
				canvas.drawBitmap(mBitmap[PAGE_CHANGE], mMatrix, mPaint);
		}
		
		super.onDraw(canvas);		
	}

	public boolean isAnimating() {
		return mAnimating;
	}
	
	private void startAnimation(int direction) {
		Log.d(TAG, "startAnimation");
		if(mAnimating)
			return;

		initAnimation(direction);
		
		try {
			Log.d(TAG, "start Timer");
			if(mTimer!=null)
				mTimer.cancel();
			mTimer = new Timer();
			mTimer.schedule(
				new TimerTask(){
					public void run() {
						mHandler.post(new Runnable(){
						public void run(){
							Log.d(TAG, "running Timer...");
							doAnimation();
							postInvalidate();
						}
					});
				}        	
		    }, mInterval,mInterval);
			
		}catch(IllegalStateException e) {
			// done~!
			mAnimating = false;
		}
	}
	
	private void flushAnimation(int direction) {
		try {
			Log.d(TAG, "start Timer");
			if(mTimer!=null)
				mTimer.cancel();
			mTimer = new Timer();
			mTimer.schedule(
				new TimerTask(){
					public void run() {
						mHandler.post(new Runnable(){
						public void run(){
							Log.d(TAG, "running Timer...");
							doAnimation();
							postInvalidate();
						}
					});
				}        	
		    }, mInterval,mInterval);
			
		}catch(IllegalStateException e) {
			// done~!
			mAnimating = false;
		}
		
	}
	
	private void stopAnimation() {
		Log.d(TAG, "stopAnimation");
		mBitmap[PAGE_BASE] = mBitmap[PAGE_CHANGE];
		if(mTimer!=null) {
			mTimer.cancel();
			mTimer.purge();
		}
		mTimer = null;
		mAnimating = false;		
	}

	
	int mWidth;
	int mHeight;
	int mPosition = 0;
	int mAccelPixels = 0;
	ByteBuffer mBuffer=null;

	private void initAnimation(int direction) {
		mDirection = direction;
		mAnimating = true;
		mWidth = getWidth();
		mHeight = getHeight();
		if(direction==DIRECTION_NEXT)	mPosition = mWidth;			
		else	mPosition = 0;
		mAccelPixels = Math.max((int)(mWidth/10), 10);
		//mAccelPixels = Math.min((int)(mWidth/10), ACCEL);
	}

	private void doAnimation() {
		Log.d(TAG, "mDirection=" + mDirection + ", mPosition=" + mPosition + ", Accels=" + mAccelPixels + ", Width=" + mWidth);
		if(mDirection==DIRECTION_NEXT) {
			mPosition -= mAccelPixels;
			if(mPosition<=0) {
				stopAnimation();				
			}
		} else {
			mPosition += mAccelPixels;
			if(mPosition>=mWidth) {
				stopAnimation();
			}
		}
	}

	private void doneAnimation() {
	}
	
}
